#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int maxn = 1e5 + 10;
int arr[maxn];
int in[maxn], out[maxn];
int tree[maxn]; // 树状数组, 入序为 i 的节点对应的数组
vector<int> v[maxn]; // 存树
int n,m;
int cnt; // 记录入序
// 整数最后一位 1 及其后面的 0
int lowbit(int x){
	return x&(-x);
}

// 更新树状数组
// 每次 + lowbit(i)
void update(int val, int pos){ // 一直要注意这个 val 是改变量
	for(int i=pos;i<=n;i+=lowbit(i)){
		tree[i]^=val;
	}
}
// 获取前缀异或和
int getprefix(int pos){
	int res=0;
	for(int i=pos;i>=1;i-=lowbit(i)){
		res^=tree[i];
	}
	return res;
}

// 获取 DFS 序
void dfs(int pos, int fa){
	in[pos]=++cnt; // 入序
//	update(arr[pos], cnt);
	for(const int & nx:v[pos]){
		if(nx==fa){
			continue;
		}
		dfs(nx, pos);
	}
	out[pos]=cnt; // 出序
}

void solve(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>arr[i]; // 每个点的权值
//		update(arr[i], i);
	}
	for(int i=1;i<=n-1;i++){
		int a, b;
		cin>>a>>b;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	
	dfs(1, 0);
	for(int i=1;i<=n;i++){
		update(arr[i], in[i]);
	}
	for(int i=1;i<=m;i++){
		int op, x, y;
		cin>>op;
		if(op==1){
			cin>>x>>y; // x 改为 y
			// in[x], 表示对应的 tree 中的位置
			update(arr[x]^y, in[x]); // 注意提供的是修改量
			arr[x]=y; // 这里需要非常注意  arr[i] 变化了 !!!!
		} else{
			cin>>x;
			int l=in[x], r=out[x];
			cout<<(getprefix(r)^getprefix(l-1))<<'\n';
		}
	}
	
}

signed main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	solve();
	return 0;
}

